/***********************************************************************
 * Copyright (c)  2008 - 2021, dxtc Co.,Ltd .
 * All rights reserved.
 * Filename    : owh.c
 * Description : one-wire example source file
 * Author(s)   : liujia
 * version     : V1.0
 * Modify date : 2023-02-14
 ***********************************************************************/
#include "owh.h"
/*计算crc的校验值*/
static uint16_t OWH_Get_CRC16(uint8_t *pdata, uint32_t length)
{
	uint8_t i;
	uint32_t len;
	uint16_t crc_value = 0;
	uint8_t inbyte, mix;

	for(len=0; len<length; len++)
	{
		inbyte = pdata[len];
		for (i=0; i<8; i++)
		{
			mix = ((uint8_t)crc_value ^ inbyte) & 0x01;
			crc_value = crc_value >> 1;
			if(mix)
				crc_value = crc_value ^ 0xA001;
			inbyte = inbyte >> 1;
		}
	}
	crc_value ^= 0xFFFF;
	return crc_value;
}

/*核对crc校验值是不是正确的*/
//return:	0: SUCCESS; 1:  FAIL
static uint8_t OWH_Chk_CRC16(uint8_t *pdata, uint32_t length, uint16_t crc_chk)
{
	uint8_t i;
	uint32_t len;
	uint16_t crc_value = 0;
	uint8_t inbyte, mix;

	for(len=0; len<length; len++)
	{
		inbyte = pdata[len];
		for (i=0; i<8; i++)
		{
			mix = ((uint8_t)crc_value ^ inbyte) & 0x01;
			crc_value = crc_value >> 1;
			if(mix)
				crc_value = crc_value ^ 0xA001;
			inbyte = inbyte >> 1;
		}
	}
	crc_value ^= 0xFFFF;
	if(crc_value ^ crc_chk)
		return 1;

	return 0;
}

// uint8_t OWH_ResetDevice(uint8_t type, uint8_t *romid)
// {
// 	uint8_t ret;
	
// 	ret = 0;

// 	return ret;
// }

/*等待命令回复*/
uint8_t OWH_Command_Response(OWH_COMMAND *cmd, OWH_RESPONSE *resp, uint32_t wait_ms)
{
	uint8_t ret;
	uint16_t data_crc16 = 0;
	uint32_t cmd_len, resp_len;
	
	data_crc16 = OWH_Get_CRC16(&cmd->command, cmd->para_len + 2);	//cmd + para_len

	cmd->para_data[cmd->para_len] = (uint8_t)(data_crc16>>8);
	cmd->para_data[cmd->para_len+1] = (uint8_t)(data_crc16>>0);

	cmd_len = cmd->para_len + 4;	//cmd + para_len + para_data[n] + crc16

	ret = Device_Write(VHW_IIC_ACL16,&cmd->command, cmd_len,NULL);
	if (ret)
	{
		return ret;
	}
	
	owh_systick_delay_ms(wait_ms);
	
	resp_len = Device_Read(VHW_IIC_ACL16,&resp->resp_len,0,0);	//resp_len + resp_code + resp_data[n] + crc16
	if (resp_len == 0)
	{
		return 1;
	}

	data_crc16 = resp->resp_data[resp->resp_len-1];
	data_crc16 <<= 8;
	data_crc16 |= resp->resp_data[resp->resp_len];

	ret = OWH_Chk_CRC16(&resp->resp_len, resp->resp_len + 1, data_crc16);
	if (ret)
	{
		return ret;
	}
	
	if(resp->resp_code != 0xAA)
	{
		return resp->resp_code;
	}

	return 0;
}

void owh_printf_buff_byte(const uint8_t* buff, uint32_t length)
{
	uint32_t i;

	for(i=0;i<length;i++)
	{
		printf("%02X", buff[i]);	
	}
	printf("\r\n");
}

void owh_printf_buff_word(const uint32_t* buff, uint32_t length)
{
	uint32_t i;

	for(i=0;i<length;i++)
	{
		printf("%08X ", (unsigned int)buff[i]);	
	}
	printf("\r\n");
}

void owh_systick_delay_us(uint32_t us)
{
	co_delay_us(us);
}

void owh_systick_delay_ms(uint32_t ms)
{
	co_delay_ms(ms);
}
//iics使能设置
uint8_t Hal_Owh_IIC_Init(void)
{
	uint8_t pcmid[10] = {0};
	Device_Enable(VHW_IIC_ACL16);
	printf("owh iic init\r\n");
	return Hal_Owh_Read_PCM_ID(pcmid);
}
//iic失能
void Hal_Owh_IIC_Deinit(void)
{
	Device_Disable(VHW_IIC_ACL16);
}

uint8_t Hal_Owh_ChkCrc_Rom_ID(uint8_t *rom_id)
{
	uint8_t ret;
	
	ret = Cmd_Owh_ChkCrc_RomdID(rom_id);
	
	OwhprintfB8(rom_id, 8);
	if(ret)
	{
		OwhprintfS("ROM_ID_CHK_CRC_FAIL:  ");	
	}
	else
	{
		OwhprintfS("ROM_ID_CHK_CRC_PASS:  ");
	}
	OwhprintfB8(rom_id, 8);

	return ret;
}
//获取ROM_ID和MANU_ID
uint8_t Hal_Owh_Read_PCM_ID(uint8_t *pcm_id)
{
	uint8_t ret;

	uint8_t id[10] = {0};

	ret = Cmd_Owh_Get_PCM_ID(id);//0xB2
	if(ret)
	{
		return ret;
	}

	memcpy(pcm_id, id, sizeof(id));

	OwhprintfS("PCM_ID:  ");
	OwhprintfB8(id, sizeof(id));

	return 0;
}

//内部默认有值，每次写一次，里面的count值就减少1
uint8_t Hal_Owh_Write_Counter_Value(void)
{	
	uint8_t ret;
	
	ret = Cmd_Owh_Set_Counter_Value();//0x24
	if(ret != 0x00)
	{
		return ret;
	}
	
	
	return 0;
}

//获取里面的count值
uint8_t Hal_Owh_Read_Counter_Value(uint32_t *counter_value)
{	
	uint8_t ret;
	uint32_t u32_counter_value = 0;
	
	ret = Cmd_Owh_Get_Counter_Value(&u32_counter_value);
	if(ret != 0x00)
	{
		return ret;
	}
	*counter_value = u32_counter_value;
	OwhprintfS("Counter_Value: %06X\r\n", (unsigned int)u32_counter_value);
	
	return 0;
}
//验证内部数字证书
uint8_t Hal_Owh_Verify_Digital_Signature(void)
{
	uint8_t page_index = 0;
	uint8_t u8_challenge[32] = {0x12,0xE6,0x37,0x4B,0xA8,0xB2,0x62,0x56,0x1B,0xD9,0xAB,0x84,0xBE,0xB3,0x18,0x8D,0xF1,0x6D,0x31,0xAC,0x97,0xAF,0x11,0x5E,0xCA,0x7B,0xBC,0x68,0xCD,0x59,0xB3,0x17};
	
	if(Cmd_Owh_Verify_Digital_Signature_Initial(page_index))
	{
		OwhprintfS("Cmd_Owh_Verify_Digital_Signature_Initial -> Fail.\r\n");
		OwhprintfS("sdg_firmware_fail\r\n");

		return 1;
	}
	OwhprintfS("Cmd_Owh_Verify_Digital_Signature_Initial -> Pass.\r\n");
	if(Cmd_Owh_Verify_Digital_Signature_Test(page_index, u8_challenge))
	{
		OwhprintfS("Cmd_Owh_Verify_Digital_Signature_Test -> Fail.\r\n");

		return 2;
	}
	OwhprintfS("Cmd_Owh_Verify_Digital_Signature_Test -> Pass.\r\n");
	
	return 0;
}

/*
UART Printf Data:
ROM_ID:  B2 04 B6 40 00 00 01 AC 
PCM_ID:  B2 04 B6 40 00 00 01 AC 64 00 
DC_CNT:  131061.
Verify_Digital_Signature Test Pass.
*/
void APP_OWH_Check(void)
{
	uint8_t bRet;
	uint8_t romid[8] = {0};
	uint8_t pcmid[10] = {0};
	uint8_t read_data[32] = {0};
	uint8_t write_data[32] = {0};

	uint32_t dcvalue = 0;

	Hal_Owh_IIC_Init();

	bRet = Hal_Owh_Read_PCM_ID(pcmid);//0xB2
	if(bRet)
	{
		printf("Read_PCM_ID Test Fail.\r\n");
		return;
	}

	bRet = Hal_Owh_ChkCrc_Rom_ID(pcmid);//check crc
	if(bRet)
	{
		printf("ChkCrc_Rom_ID Test Fail.\r\n");
		return;
	}

	bRet = Hal_Owh_Write_Counter_Value();//0x24
	if(bRet)
	{
		printf("Write_Counter_Value Test Fail.\r\n");
		return;
	}

	bRet = Hal_Owh_Read_Counter_Value(&dcvalue);//0xc0
	if(bRet)
	{
		printf("Read_Counter_Value Test Fail.\r\n");
		return;
	}
	printf("DC_CNT:  %d.\r\n",dcvalue);

	bRet = Cmd_Owh_Get_Memory_Page(1,read_data);
	if(bRet)
	{
		printf("Get_Memory_Page Test Fail.\r\n");
		return;
	}
	owh_printf_buff_byte(read_data,32);
	for(uint8_t i = 0;i<32;i++)
	{
		write_data[i]=i;
	}

	bRet = Cmd_Owh_Set_Memory_Page(1,write_data);
	if(bRet)
	{
		printf("Set_Memory_Page Test Fail.\r\n");
		return;
	}

	bRet = Hal_Owh_Verify_Digital_Signature();
	if(bRet)
	{
		printf("Verify_Digital_Signature Test Fail.\r\n");
		return;
	}
	
	printf("Verify_Digital_Signature Test Pass.\r\n");
}
/*
[2023/2/19 17:53:35:454] Bat_Acl16_Task
[2023/2/19 17:53:35:470] PCM_ID:  E504B64000007BAC6400
[2023/2/19 17:53:35:470] E504B64000007BAC
[2023/2/19 17:53:35:470] ROM_ID_CHK_CRC_PASS:  E504B64000007BAC
[2023/2/19 17:53:35:486] Counter_Value: 01FFC5
[2023/2/19 17:53:35:486] DC_CNT:  131013.
[2023/2/19 17:53:35:502] 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
[2023/2/19 17:53:35:902] Cmd_Owh_Verify_Digital_Signature_Initial -> Pass.
[2023/2/19 17:53:36:286] Cmd_Owh_Verify_Digital_Signature_Test -> Pass.
[2023/2/19 17:53:36:286] Verify_Digital_Signature Test Pass.
*/

